use anyhow::Result;
use async_channel::bounded;
use futures::prelude::*;
use smol::Task;
use std::thread;

mod config;
mod shunt;

fn main() -> Result<()> {
    // Same number of threads as there are CPU cores.
    let num_threads = num_cpus::get().max(1) - 1;
    println!("num_threads = {:?}", num_threads + 1);

    // Run the thread-local and work-stealing executor on a thread pool.
    for _ in 0..num_threads {
        // A pending future is one that simply yields forever.
        thread::spawn(|| smol::run(future::pending::<()>()));
    }

    let cfg = config::read()?;

    let task = Task::spawn(shunt::listen(cfg));

    let (s, r) = bounded::<()>(1);
    ctrlc::set_handler(move || {
        if let Err(e) = smol::block_on(s.send(())) {
            println!("ctrlc fail {:?}", e);
        }
    })?;

    smol::run(r.recv())?;
    smol::run(task.cancel());
    println!("program quit");
    Ok(())
}
